home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / bbs / doorinfo.zip / ZMSEND.C < prev   
C/C++ Source or Header  |  1997-05-14  |  25KB  |  1,187 lines

  1. /*
  2. **************************************************************************
  3. **
  4. ** Doors program to send files via zmodem
  5. **
  6. ** Compile instructions for MSC 5.1 and 6.0
  7. ** Note - structs.h hsz.h and bbscfg.h are required.
  8. **        these files, and lmtca.obj, are available in doorinfo.zip
  9. **
  10. **  cl /c /AL /Gs zmsend.c
  11. **  link /st:4096 zmsend lmtca fsubs;
  12. **
  13. **************************************************************************
  14. */
  15.  
  16. /*
  17. #define DBG
  18. */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <dos.h>
  24. #include <time.h>
  25. #include "hsz.h"
  26. #include "structs.h"
  27. #include "bbscfg.h"
  28. #include "fossil.h"
  29. #include "c:\mt\tcb.h"
  30. #include "crctab.c"
  31.  
  32. #include "sendraw.h"
  33.  
  34. void sendzrqinit(void);
  35. void sendzfile(char *name);
  36. void waitforzack(void);
  37. void waitforzrinit(void);
  38. void sendzsinit(void);
  39. void sendzfin(void);
  40. void sendzeof(void);
  41. void sendbindata(char *buf, int length, int frameend);
  42. void zsda32(char *buf, int length, int frameend);
  43. void zsendline(int c);
  44. void sendzdata(void);
  45. void sendbinhdr(char *buf, int count);
  46. void sendhexhdr(char *buf, int count);
  47. void bsend(char *str);
  48. int endtask(void);
  49. int sendblock(void);
  50. void clear_queue(int q);
  51. int calccrc(char *buf, int len);
  52. int calccrc32(char *buf, int len);
  53. int check_timer(time_t tim);
  54. void getfilename(char *buf1, char *buf2);
  55. int check_q(void);
  56. int check_ring_buf(void);
  57.  
  58. #define MY_buf_size 12*1024
  59.  
  60. typedef struct acct_rec acctp[];
  61. typedef struct user_rec userp[];
  62.  
  63. struct cfg_rec far *cfg;    /* pointer to BBSCFG record */
  64.  
  65. acctp far *acct;
  66. userp far *user;        /* pointer to an array of user_rec
  67.                  * structue\res */
  68. time_t t;
  69.  
  70. char MY_buf[MY_buf_size];
  71.  
  72. FILE *logfp;
  73.  
  74. int sendbufsize;
  75. int blocks_since_nak;
  76.  
  77. struct find_t fin;
  78.  
  79. #define NAK 21
  80. #define CAN 24
  81.  
  82. int blocksize;
  83. unsigned int rbufsiz;        /* the receiver's buffer size */
  84.  
  85. char fname[80];
  86. char hdrbuf[40];
  87. char buffer[2100];
  88. char buffer2[2100];
  89. char secbuf[2100];
  90.  
  91. char namebuf[1000];
  92.  
  93. long filepos;
  94. long filepos_save;
  95.  
  96. int escapeall = 0;        /* normally we don;t escape all characters */
  97. int crc32 = 0;            /* use 16 or 32 bit crc */
  98. int waitforack = 0;        /* streaming/nonstreaming */
  99.  
  100. int recvmode;            /* used to determine how much of header
  101.                  * received */
  102. int hdrincnt;            /* must receive 13 bytes */
  103.  /* type, 8 bytes of flags, 4 bytes of crc, in ascii hex */
  104.  
  105. int cancount = 0;
  106.  
  107. struct msg1
  108. {                /* used for text in/out */
  109.     int m1typ;
  110.     int m1num;            /* line number */
  111.     char m1text[1000];
  112. }  *m1;
  113.  
  114. struct msg3
  115. {                /* the initial message with line num and
  116.                  * queue nums */
  117.     int m3typ;            /* must be 7 */
  118.     int m3line;
  119.     int m3inq;
  120.     int m3outq;
  121.     void far *acctptr;
  122.     void far *userptr;
  123.     int maxline;
  124.     struct cfg_rec far *cfgptr;    /* pointer to BBSCFG record */
  125. }  *m3;
  126.  
  127. char lbuf[128];            /* a little work buffer */
  128.  
  129. int who;
  130. int inq, outq;
  131.  
  132. FILE *fp;
  133.  
  134. void main(int argc, char *argv[])
  135. {
  136.     int j, k, n;
  137.     int alldone = 0;
  138.  
  139.     logfp = fp = NULL;
  140.  
  141.     setpri(7);
  142.  
  143.     m1 = (struct msg1 *) buffer;
  144.     m3 = (struct msg3 *) buffer;
  145.  
  146. /*
  147. ** wait for the initialization event from FALKEN.
  148. ** it will be event type 7.
  149. ** If for some reason we get an event type 8, we must terminate.
  150. */
  151.     m3->m3typ = 0;
  152.     time(&t);
  153.     while (m3->m3typ != 7)
  154.     {
  155.     if (testmsg(1))
  156.     {
  157.         recvmsg(1, buffer, 1000);
  158.         if (m3->m3typ == 8)
  159.         {
  160.         endtask();
  161.         }
  162.     }
  163.     else if (check_timer(t) > 10)
  164.     {
  165.         endtask();
  166.     }
  167.     relinq();
  168.     }
  169.  
  170.     acct = m3->acctptr;
  171.     user = m3->userptr;
  172.     cfg = m3->cfgptr;
  173.  
  174. /*
  175. ** get the input and output queue numbers we have been assigned,
  176. ** and which line this user is logged on to.
  177. */
  178.  
  179.     inq = m3->m3inq;
  180.     outq = m3->m3outq;
  181.     who = m3->m3line;
  182.  
  183. /*
  184. **  Now the main loop -
  185. */
  186.  
  187.     if (argc > 1)
  188.     {
  189.     strcpy(namebuf, argv[1]);
  190.     j = 2;
  191.     while (j < argc)
  192.     {
  193.         strcat(namebuf, ",");
  194.         strcat(namebuf, argv[j++]);
  195.     }
  196.     clear_queue(inq);
  197.     }
  198.     else            /* need an event with file names in it */
  199.     {
  200.     n = 0;            /* wait for the text message with filenames */
  201.     time(&t);
  202.     for (;;)
  203.     {
  204.         if (testmsg(inq))
  205.         {
  206.         recvmsg(inq, buffer, 1000);
  207.         if (m1->m1typ == 8)
  208.         {
  209.             endtask();
  210.         }
  211.         else if (m1->m1typ == 1)
  212.         {
  213.             if (strncmp(m1->m1text, "filename=", 9) == 0)
  214.             {
  215.             strcpy(namebuf, m1->m1text + 9);
  216.             break;
  217.             }
  218.         }
  219.         }
  220.         if (check_timer(t) > 30)
  221.         {
  222.         endtask();
  223.         }
  224.         relinq();
  225.     }
  226.  
  227.     }
  228.     for (j = 0; namebuf[j]; j++)
  229.     {
  230.     if (namebuf[j] == ' ')
  231.         namebuf[j] = ',';
  232.     }
  233.  
  234. /*
  235. ** If this is a mux line, we have to wait for ack after every block,
  236. ** to prevent overrunning the mux's buffers
  237. */
  238.  
  239.     if (strnicmp(cfg->modem_init_str[who], "mux", 3) == 0)
  240.     {
  241.         bsend("Zmodem cannot be run on a multiplexed line.\r\n");
  242.         bsend("Please restart your download with Xmodem or Ymodem.\r\n");
  243.     delay(1);
  244.     exit(0);
  245.     }
  246.  
  247.  
  248.     m1->m1typ = 8;
  249.     send_md_msg(outq, buffer, 2);
  250.     delay(1);
  251.  
  252.     bsend("Zmodem Batch file download activated.\r\n");
  253.     bsend("Start your Zmodem transfer now....\r\n");
  254.  
  255. /*
  256. ** Now we have to establish the zmodem dialogue.  We are the sender,
  257. ** so we have to send ZRQINIT packets to the receiver telling him we
  258. ** are ready to go!
  259. */
  260.  
  261.     sendbufsize = 1024;        /* start at 1K bytes */
  262.     blocks_since_nak = 0;
  263.  
  264.     n = 0;            /* ZRINIT not received yet */
  265.     time(&t);
  266.     j = 0;            /* how many ZRQINIT packets have we sent ? */
  267.     recvmode = 0;        /* no pad received */
  268.     hdrincnt = 0;
  269.     sendzrqinit();        /* send the first zrqinit packet */
  270.     while (n == 0)
  271.     {
  272.     if (k = check_q())    /* see if we got a header in */
  273.     {
  274.         switch (k)
  275.         {
  276.         case 1:    /* packet received */
  277.             if (hdrbuf[0] == ZRINIT)
  278.             {
  279.             n = 1;    /* what we were waiting for! */
  280.             if ((hdrbuf[1 + ZF0] & CANFDX) &&
  281.                 (hdrbuf[1 + ZF0] & CANOVIO))
  282.                 waitforack = 0;
  283.             else
  284.                 waitforack = 1;
  285.             if (hdrbuf[1 + ZF0] & ESCCTL)
  286.                 escapeall = 1;
  287.             else
  288.                 escapeall = 0;
  289.  
  290.             if (hdrbuf[1 + ZF0] & CANFC32)
  291.                 crc32 = 1;
  292.             else
  293.                 crc32 = 0;
  294.             rbufsiz = (hdrbuf[1 + ZP1] << 8) + hdrbuf[1 + ZP0];
  295. /*
  296. ** If receiver has set the buffer size variable to non-zero, it
  297. ** indicates the largest buffer (window) he can have outstanding.
  298. ** If 0, we can send at will, otherwise, we will only send one
  299. ** block at a time, and wait for the ack.
  300. ** THIS IS A KLUGE!
  301. ** At some point, we should keep track of outstanding (un-acked)
  302. ** bytes, and turn transmitter off then, rather than just blindly
  303. ** sending one block and waiting for ack.
  304. */
  305.             if (rbufsiz != 0)
  306.                 waitforack = 1;
  307.             else
  308.                 waitforack = 0;
  309.             }
  310.             break;
  311.         case 4:    /* no data waiting, so outbuf counter ret's */
  312.             break;
  313.         case 0:    /* got data in, but not complete header */
  314.             time(&t);    /* reset the timeout */
  315.             break;
  316.         }
  317.     }
  318.     if (!n && (check_timer(t) > 1))
  319.     {
  320.         if (++j > 60)
  321.         {
  322.         endtask();    /* waited too long for zrinit */
  323.         }
  324.         sendzrqinit();
  325.         time(&t);
  326.     }
  327.     }
  328.  
  329. /*
  330. ** We got the ZRINIT packet, so now we send a ZSINIT packet with
  331. ** various options set for every file we wish to send.
  332. */
  333.     sendzsinit();
  334.     waitforzack();
  335.  
  336.     while (alldone == 0)
  337.     {
  338.     getfilename(namebuf, fname);
  339.  
  340. /*
  341. ** when all file names have been exhausted, get out.
  342. */
  343.     if (!strlen(fname))
  344.     {
  345.         sendzfin();
  346.         alldone = 1;
  347.     }
  348.     else
  349.     {
  350.         sendzfile(fname);
  351.         waitforzrinit();
  352.     }
  353.     }                /* end outer forever loop */
  354.     bsend("\rTransfer Successful.\r\r");
  355.     delay(1);
  356.     endtask();
  357. }
  358.  
  359. void sendzrqinit()
  360. {
  361.     int j;
  362.     lbuf[0] = ZRQINIT;        /* type */
  363.     for (j = 1; j < 5; j++)
  364.     lbuf[j] = 0;        /* set flags to 0 */
  365.     sendhexhdr(lbuf, 5);
  366. }
  367.  
  368. void sendzfile(name)
  369. char *name;
  370. {
  371.     int j, k, n;
  372.     int datacount;
  373.     int lastframe;
  374.  
  375.     char *ip;
  376.     char outbuf[80];
  377.     char obuf[16];
  378.  
  379.     ip = (char *) &filepos;
  380.     obuf[0] = ZFILE;
  381.     filepos_save = 0L;
  382.     filepos = 0L;        /* initialize filepos to beginning of file */
  383. /*
  384. ** Flags - ZF1 set for binary transfer, optional file recovery of
  385. ** aborted transfers.
  386. */
  387.     obuf[1 + ZF0] = ZCBIN;
  388.     obuf[1 + ZF1] = 0;
  389.     obuf[1 + ZF2] = 0;
  390.     obuf[1 + ZF3] = 0;
  391.  
  392.     sendbinhdr(obuf, 5);    /* send the header */
  393.  
  394.     sprintf(outbuf, "%s %ld", name, fin.size);    /* fin loaded in
  395.                          * getfilename() */
  396.     j = strlen(outbuf);
  397.     for (k = 0; outbuf[k] != ' '; k++);
  398.     outbuf[k] = '\0';        /* insert a null between name and size */
  399.     k = 0;
  400.     for (n = 0; n < j; n++)
  401.     secbuf[k++] = outbuf[n];/* move name, size */
  402.     secbuf[k++] = '\0';        /* null to terminate the file len */
  403.  
  404.     sendbindata(secbuf, k, ZCRCW);
  405.     datacount = k;
  406.  
  407.     recvmode = 0;
  408.     hdrincnt = 0;
  409.  
  410.     waitforzack();
  411.  
  412.     sendzdata();
  413.  
  414.     lastframe = ZCRCG;
  415.  
  416. /*
  417. ** Now we loop, checking how many bytes are free in the line's
  418. ** transmit buffer, checking the input queue, and sending binary
  419. ** subpackets whenever we can.
  420. */
  421.     for (;;)
  422.     {
  423.     if (k = check_q())    /* see if we got a header in */
  424.     {
  425.         switch (k)
  426.         {
  427.         case 1:    /* packet received */
  428.             switch (hdrbuf[0])
  429.             {
  430.             case ZRPOS:
  431.             case ZACK:
  432.                 ip[0] = hdrbuf[1 + ZP0];
  433.                 ip[1] = hdrbuf[1 + ZP1];
  434.                 ip[2] = hdrbuf[1 + ZP2];
  435.                 ip[3] = hdrbuf[1 + ZP3];
  436.                 if ((lastframe != ZCRCW) && (lastframe != ZCRCE))
  437.                 sendbindata(outbuf, 0, ZCRCE);    /* empty CRCE packet */
  438.                 sendzdata();    /* send a data header */
  439.                 goto sendnext;
  440.                 break;
  441.             case ZSKIP:    /* receiver says skip this file */
  442.                 return;    /* return to main routine */
  443.                 break;
  444.             case ZABORT:    /* receiver aborts batch file xfer */
  445.                 lbuf[0] = ZFIN;
  446.                 lbuf[1] = lbuf[2] = lbuf[3] = lbuf[4] = 0;    /* flags to 0 */
  447.                 sendhexhdr(lbuf, 5);
  448.                             bsend("\r\n\nZMODEM transfer aborted by receiver !\r\n\n");
  449.                 delay(2);
  450.                 endtask();
  451.             case ZNAK:    /* last header was garbled.  resend
  452.                      * it */
  453.                 blocks_since_nak = 0;
  454.                 if (sendbufsize > 512)
  455.                 sendbufsize = 512;
  456.                 sendbinhdr(obuf, 5);
  457.                 sendbindata(secbuf, datacount, ZCRCW);
  458.                 break;
  459.             }
  460.             break;
  461. /*
  462. ** A little tricky here.
  463. ** Any time the the output buffer is empty, we will
  464. ** send the next data block.  If we are to wait for an acknowledgement,
  465. ** then we wait for the ack, then send the next header right away.
  466. ** The header is less than 100 bytes, so we come through again, and see
  467. ** that the outbuf count < 100, and we go ahead and send the data to go
  468. ** with that header.
  469. **
  470. */
  471.  
  472.         case 4:    /* outbuf counter received. */
  473.         sendnext:
  474. /*
  475. ** If we got a zrpos or a zrnak, we have reset our filepos pointer,
  476. ** so, if the old filepos and the new one are different, there was
  477. ** an error on a block.  If so, knock the block size down.
  478. ** When we get 4 good blocks through, increment block size.
  479. */
  480.             if (filepos == filepos_save)    /* good block ? */
  481.             {
  482.             if (blocks_since_nak < 2)
  483.                 blocks_since_nak++;
  484.             else
  485.             {
  486.                 blocks_since_nak = 0;    /* start counting again */
  487.                 if (sendbufsize < 1024)
  488.                 sendbufsize = 1024;
  489.             }
  490.             }
  491.             else    /* error - resending a block */
  492.             {
  493.             blocks_since_nak = 0;
  494.             if (sendbufsize > 512)
  495.                 sendbufsize = 512;
  496.             }
  497.  
  498.             lastframe = j = sendblock();    /* send the next block */
  499.             switch (j)    /* sendblock returns type of block sent */
  500.             {
  501.             case ZCRCW:
  502.                 waitforzack();    /* must wait for ack */
  503.                 sendzdata();    /* need to send new packet
  504.                          * hdr */
  505.                 break;
  506.             case ZCRCE:
  507.                 sendzeof();
  508.                 if (fp != NULL)
  509.                 {
  510.                 fclose(fp);
  511.                 fp = NULL;
  512.                 }
  513.                 return;    /* now wait for new zrinit */
  514.                 break;
  515.             }
  516.             break;
  517.         }            /* end outer switch */
  518.     }            /* end if check_q */
  519.     }                /* end for(;;) */
  520. }
  521.  
  522. /*
  523. ** Utility routines follow
  524. **
  525. ** These routines call Multidos interface routines which are available
  526. ** with the FALKEN  Doors development kit.
  527. **
  528. ** See the file MDOS.TXT for a description of the interface routines.
  529. */
  530.  
  531. /*
  532. ** wait for a hex header that acknowledges a block
  533. ** all ZACK frames contain a file offset. set it up.
  534. */
  535.  
  536. void waitforzack()
  537. {
  538.     int k, n;
  539.     char *ip;
  540.  
  541.     ip = (char *) filepos;
  542.     recvmode = 0;
  543.     hdrincnt = 0;
  544.     n = 0;
  545.  
  546.     while (n == 0)
  547.     {
  548.     if (k = check_q())    /* see if we got a header in */
  549.     {
  550.         switch (k)
  551.         {
  552.         case 1:    /* packet received */
  553.             switch (hdrbuf[0])
  554.             {
  555.             case ZRINIT:
  556.                 sendzsinit();
  557.                 break;
  558.             case ZACK:
  559.             case ZRPOS:
  560.                 n = 1;    /* what we were waiting for! */
  561.                 ip[0] = hdrbuf[1 + ZP0];    /* get new file position */
  562.                 ip[1] = hdrbuf[1 + ZP1];
  563.                 ip[2] = hdrbuf[1 + ZP2];
  564.                 ip[3] = hdrbuf[1 + ZP3];
  565.                 break;
  566.             case ZNAK:
  567.                 memcpy(buffer, buffer2, 1100);
  568.                 sendraw(who, buffer + 4, m1->m1num);
  569.                 break;
  570.             }
  571.             break;
  572.         case 4:    /* no data - btuoba returned */
  573.             break;
  574.         }
  575.     }
  576.     }
  577. }
  578.  
  579.  
  580. void waitforzrinit()
  581. {
  582.     int k, n;
  583.  
  584.     recvmode = 0;
  585.     hdrincnt = 0;
  586.     n = 0;
  587.  
  588.     while (n == 0)
  589.     {
  590.     if (k = check_q())    /* see if we got a header in */
  591.     {
  592.         switch (k)
  593.         {
  594.         case 1:    /* packet received */
  595.             switch (hdrbuf[0])
  596.             {
  597.             case ZRPOS:
  598.             case ZACK:
  599.             case ZNAK:
  600.                 sendzeof();
  601.                 break;
  602.             case ZRINIT:
  603.                 n = 1;
  604.                 break;
  605.             case ZABORT:
  606.                 delay(1);
  607.                 endtask();
  608.                 break;
  609.             }
  610.             break;
  611.         case 4:
  612.             break;
  613.         }
  614.     }
  615.     }
  616. }
  617.  
  618. void sendzsinit()
  619. {
  620.     int j;
  621.  
  622.     lbuf[0] = ZSINIT;        /* type */
  623.     for (j = 1; j < 5; j++)
  624.     lbuf[j] = 0;        /* set flags to 0 */
  625.     sendbinhdr(lbuf, 5);
  626.     sendbindata(lbuf, 0, ZCRCW);/* send an empty data packet - no break */
  627. }
  628.  
  629. void sendzfin()
  630. {
  631.     int j;
  632.  
  633.     lbuf[0] = ZFIN;        /* type */
  634.     for (j = 1; j < 5; j++)
  635.     lbuf[j] = 0;        /* set flags to 0 */
  636.     sendhexhdr(lbuf, 5);
  637. }
  638.  
  639. void sendzeof()
  640. {
  641.     char *cp;
  642.  
  643.     cp = (char *) &filepos;
  644.     lbuf[0] = ZEOF;        /* type */
  645.     lbuf[1 + ZP0] = cp[0];    /* set file position in the flags/position
  646.                  * bytes */
  647.     lbuf[1 + ZP1] = cp[1];
  648.     lbuf[1 + ZP2] = cp[2];
  649.     lbuf[1 + ZP3] = cp[3];
  650.     sendhexhdr(lbuf, 5);
  651.     (*acct)[who].dloads++;
  652.     (*acct)[who].download_k += filepos / 1024L;
  653. }
  654.  
  655.  
  656. char *outbuf;
  657. int outbufcnt;
  658. char lastsent;
  659.  
  660. #define xsendline(c) outbuf[outbufcnt++]=0xff&(c)
  661.  
  662. void sendbindata(buf, length, frameend)
  663. char *buf;
  664. int length;
  665. int frameend;
  666. {
  667.     unsigned short crc;
  668.     int k;
  669.  
  670.     outbuf = m1->m1text;
  671.     outbufcnt = 0;
  672.  
  673.     lastsent = 0;
  674.  
  675.     if (crc32)
  676.     zsda32(buf, length, frameend);
  677.     else
  678.     {
  679.     crc = 0;
  680.     for (k = 0; k < length; k++)
  681.     {
  682.         zsendline(buf[k]);
  683.         crc = updcrc((0377 & buf[k]), crc);
  684.     }
  685.     crc = updcrc(frameend, crc);
  686.     xsendline(ZDLE);
  687.     xsendline(frameend);
  688.  
  689.     crc = updcrc(0, updcrc(0, crc));
  690.     zsendline((crc >> 8) & 0xff);
  691.     zsendline(crc & 0xff);
  692.     }
  693.     if (frameend == ZCRCW)
  694.     {
  695.     xsendline(17);
  696.     }
  697.     sendraw(who, outbuf, outbufcnt);
  698. }
  699.  
  700. void zsda32(buf, length, frameend)
  701. char *buf;
  702. int length;
  703. int frameend;
  704. {
  705.     int c;
  706.     unsigned long crc;
  707.  
  708.     crc = 0xFFFFFFFFL;
  709.     for (; --length >= 0; ++buf)
  710.     {
  711.     c = *buf & 0377;
  712.     if (c & 0140)
  713.         xsendline(lastsent = c);
  714.     else
  715.         zsendline(c);
  716.     crc = UPDC32(c, crc);
  717.     }
  718.     xsendline(ZDLE);
  719.     xsendline(frameend);
  720.     crc = UPDC32(frameend, crc);
  721.  
  722.     crc = ~crc;
  723.     for (length = 4; --length >= 0;)
  724.     {
  725.     zsendline((int) crc);
  726.     crc >>= 8;
  727.     }
  728. }
  729.  
  730.  
  731. /*
  732.  * Send character c with ZMODEM escape sequence encoding.
  733.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  734.  */
  735.  
  736. void zsendline(c)
  737. {
  738.  
  739.     /* Quick check for non control characters */
  740.     if (c & 0140)
  741.     xsendline(lastsent = c);
  742.     else
  743.     {
  744.     switch (c &= 0377)
  745.     {
  746.         case ZDLE:
  747.         xsendline(ZDLE);
  748.         xsendline(lastsent = (c ^= 0100));
  749.         break;
  750.         case 015:
  751.         case 0215:
  752.         if ((!escapeall) && (lastsent & 0177) != '@')
  753.             goto sendit;
  754.         /* **** FALL THRU TO **** */
  755.         case 020:
  756.         case 021:
  757.         case 023:
  758.         case 0220:
  759.         case 0221:
  760.         case 0223:
  761.         xsendline(ZDLE);
  762.         c ^= 0100;
  763.     sendit:
  764.         xsendline(lastsent = c);
  765.         break;
  766.         default:
  767.         if (escapeall && !(c & 0140))
  768.         {
  769.             xsendline(ZDLE);
  770.             c ^= 0100;
  771.         }
  772.         xsendline(lastsent = c);
  773.     }
  774.     }
  775. }
  776.  
  777. void sendzdata()
  778. {
  779.     char *cp;
  780.  
  781.     cp = (char *) &filepos;
  782.     lbuf[0] = ZDATA;        /* type */
  783.     lbuf[1 + ZP0] = cp[0];    /* set file position in the flags/position
  784.                  * bytes */
  785.     lbuf[1 + ZP1] = cp[1];
  786.     lbuf[1 + ZP2] = cp[2];
  787.     lbuf[1 + ZP3] = cp[3];
  788.     sendbinhdr(lbuf, 5);
  789. }
  790.  
  791. void sendbinhdr(buf, count)
  792. char *buf;
  793. int count;
  794. {
  795.     int j, k;
  796.     char *outbuf;
  797.  
  798.     j = k = 0;
  799. /* calccrc returns new buffer length */
  800.     if (crc32)
  801.     count = calccrc32(buf, count);
  802.     else
  803.     count = calccrc(buf, count);
  804.     outbuf = m1->m1text;
  805.     j = 0;
  806.     outbuf[j++] = ZPAD;
  807.     outbuf[j++] = ZDLE;
  808.     if (crc32)
  809.     outbuf[j++] = 'C';
  810.     else
  811.     outbuf[j++] = 'A';    /* send binary header! */
  812.     for (k = 0; k < count; k++)
  813.     {
  814.     if (buf[k] == ZDLE)
  815.     {
  816.         outbuf[j++] = ZDLE;
  817.         outbuf[j++] = ZDLEE;
  818.     }
  819.     else if (escapeall)
  820.     {
  821.         if ((buf[k] & 0xc0) == 0)    /* if bits 5 and 6 reset */
  822.         {
  823.         outbuf[j++] = ZDLE;
  824.         outbuf[j++] = buf[k] | 0x40;
  825.         }
  826.         else if (buf[k] == 0x7f)
  827.         {
  828.         outbuf[j++] = ZDLE;
  829.         outbuf[j++] = 'l';
  830.         }
  831.         else if (buf[k] == 0xff)
  832.         {
  833.         outbuf[j++] = ZDLE;
  834.         outbuf[j++] = 'm';
  835.         }
  836.         else
  837.         outbuf[j++] = buf[k];
  838.     }
  839.     else            /* only escape the xon xoff stuff */
  840.     {
  841.         if (((buf[k] & 0x7f) >= 16) && ((buf[k] & 0x7f) < 20))
  842.         {
  843.         outbuf[j++] = ZDLE;
  844.         outbuf[j++] = buf[k] | 0x40;
  845.         }
  846.         else
  847.         outbuf[j++] = buf[k];
  848.     }
  849.     }                /* end for */
  850.  
  851.     memcpy(buffer2, buffer, j + 4);    /* save a copy of the last
  852.                      * transmission */
  853.     sendraw(who, outbuf, j);
  854. }
  855.  
  856.  
  857. void sendhexhdr(buf, count)
  858. char *buf;
  859. int count;
  860. {
  861.     int j, k;
  862.     char *outbuf;
  863.     char w[14];
  864.  
  865.     j = k = 0;
  866.     count = calccrc(buf, count);/* calccrc returns new buffer length */
  867.  
  868.     outbuf = m1->m1text;
  869.     j = 0;
  870.     outbuf[j++] = ZPAD;
  871.     outbuf[j++] = ZPAD;
  872.     outbuf[j++] = ZDLE;
  873.     outbuf[j++] = 'B';        /* send hex header! */
  874.     for (k = 0; k < count; k++)
  875.     {
  876.     sprintf(w, "%02x", (int) 0xff & buf[k]);
  877.     outbuf[j++] = w[0];
  878.     outbuf[j++] = w[1];
  879.     }
  880.     outbuf[j++] = '\r';
  881.     outbuf[j++] = '\n';
  882.     outbuf[j++] = 17;        /* x-on */
  883.     memcpy(buffer2, buffer, j + 4);    /* save a copy of the last
  884.                      * transmission */
  885.     sendraw(who, outbuf, j);
  886. }
  887.  
  888. /*
  889. ** Send a null terminated string to FALKEN, to be transmitted to
  890. ** a particular line;
  891. */
  892.  
  893. void bsend(str)
  894. char *str;
  895. {
  896.     sendraw(who, str, strlen(str));
  897. }
  898.  
  899. /*
  900. ** This program gracefully exits by
  901. ** sending the 'task has terminated' message to FALKEN,
  902. ** then terminating.
  903. */
  904. int endtask()
  905. {
  906. /*
  907. ** Put line parameters back the way they were
  908. */
  909.  
  910.     if (logfp != NULL)
  911.     fclose(logfp);
  912.     if (fp != NULL)
  913.     fclose(fp);
  914.     delay(1);
  915.     exit(0);
  916. }
  917.  
  918. int sendblock()
  919. {
  920.     int j;
  921.  
  922. /*
  923. ** if the file offset has changed, via a zrpos or zack, then do an
  924. ** fseek to get to the right file position
  925. */
  926.     if (filepos_save != filepos)
  927.     {
  928.     fseek(fp, filepos, SEEK_SET);
  929.     }
  930.     blocksize = fread(secbuf, 1, sendbufsize, fp);
  931.     filepos += blocksize;
  932.     filepos_save = filepos;    /* remember the old offset */
  933.     if (feof(fp))        /* end of file reached ? */
  934.     {
  935.     j = ZCRCE;
  936.     }
  937.     else
  938.     {
  939.     if (!waitforack)
  940.         j = ZCRCG;        /* we want to stream output! */
  941.     else
  942.         j = ZCRCW;        /* guess not */
  943.     j = ZCRCW;
  944.     }
  945.     sendbindata(secbuf, blocksize, j);
  946.     return j;            /* return block type sent */
  947. }
  948.  
  949.  
  950. void clear_queue(q)
  951. int q;
  952. {
  953.     while (testmsg(q) > 0)
  954.     recvmsg(q, buffer, 1024);
  955.     f_flushin(who);
  956.     f_flushout(who);
  957. }
  958.  
  959.  
  960. calccrc(buf, len)
  961. char *buf;
  962. int len;
  963. {
  964.     unsigned int c;
  965.     int j;
  966.     c = 0;
  967.     for (j = 0; j < len; j++)
  968.     c = updcrc((255 & buf[j]), c);
  969.     c = updcrc(0, c);
  970.     c = updcrc(0, c);
  971.     buf[j++] = (c >> 8) & 0xff;
  972.     buf[j++] = c & 0xff;
  973.     return j;            /* returns length of buffer, counting crc */
  974. }
  975.  
  976. calccrc32(buf, len)
  977. char *buf;
  978. int len;
  979. {
  980.     unsigned long int c;
  981.     int j, k;
  982.     c = 0xffffffffL;
  983.     for (j = 0; j < len; j++)
  984.     {
  985.     k = 0xff & buf[j];
  986.     c = UPDC32(k, c);
  987.     }
  988.     c = ~c;
  989.     for (k = 0; k < 4; k++)
  990.     {
  991.     buf[j++] = (char) c;
  992.     c >>= 8;
  993.     }
  994.     return j;            /* returns length of buffer, counting crc */
  995. }
  996.  
  997. check_timer(time_t tim)
  998. {
  999.     time_t curt;
  1000.     time(&curt);
  1001.     return ((int) curt - tim);
  1002. }
  1003.  
  1004. /*
  1005. ** We will get the next file name from buf1, and place it into buf2.
  1006. ** Notice that when we copy it into buf2, we strip off the directory
  1007. ** information, so that all we keep in buf2 is the file name itself.
  1008. ** We build a full path and file name in buf3 to use when opening
  1009. ** the file.
  1010. */
  1011.  
  1012. void getfilename(buf1, buf2)
  1013. char *buf1, *buf2;
  1014. {
  1015.     int j, k, n, m;
  1016. gnam:
  1017.     n = m = k = 0;
  1018.     while (buf1[n] == ',')
  1019.     n++;            /* skip the used spaces */
  1020.     while (buf1[n] != ',')
  1021.     {
  1022.     if (buf1[n] == '\0')
  1023.         break;
  1024.     if (buf1[n] == '\\' || buf1[n] == ':')
  1025.         m = 0;        /* no path info in this one */
  1026.     else
  1027.         buf2[m++] = buf1[n];
  1028.     lbuf[k++] = buf1[n];
  1029.     buf1[n++] = ',';    /* set to comma so we skip it next time */
  1030.     }
  1031.     buf2[m] = '\0';
  1032.     lbuf[k] = '\0';
  1033.  
  1034.     if (m == 0 || k == 0)
  1035.     return;            /* no file name found! */
  1036.  
  1037.     j = _dos_findfirst(lbuf, _A_NORMAL, &fin);    /* is it a real file ? */
  1038.  
  1039.     if (j)
  1040.     goto gnam;
  1041.  
  1042.     fp = fopen(lbuf, "rb");
  1043.  
  1044.     if (fp == NULL)
  1045.     goto gnam;
  1046.     setvbuf(fp, MY_buf, _IOFBF, MY_buf_size);
  1047. }
  1048.  
  1049. check_q()
  1050. {
  1051.     int j, k, m, n;
  1052.  
  1053.     n = 0;
  1054.  
  1055.     if ((n = check_ring_buf()) == 0)    /* return # chars read */
  1056.     {
  1057.     if (testmsg(inq))
  1058.     {
  1059.         recvmsg(inq, buffer, 1000);
  1060.         n = 1;
  1061.     }
  1062.     else
  1063.     {
  1064.         n = f_status(who);
  1065.         if (n & 0x6000)    /* output buffer empty ? */
  1066.         return 4;
  1067.         else
  1068.         return 5;
  1069.     }
  1070.     }
  1071.  
  1072.     switch (m1->m1typ)
  1073.     {
  1074.     case 8:        /* terminate command */
  1075.         endtask();
  1076.     case 2:        /* binary data in */
  1077.         m1->m1text[m1->m1num] = '\0';
  1078.         for (j = 0; j < m1->m1num; j++)
  1079.         {
  1080.         if (m1->m1text[j] == ZDLE)
  1081.         {
  1082.             if (++cancount >= 4)
  1083.             endtask();
  1084.         }
  1085.         else
  1086.             cancount = 0;
  1087.         switch (recvmode)
  1088.         {
  1089.             case 0:    /* waiting for zpad */
  1090.             if (m1->m1text[j] == ZPAD)
  1091.             {
  1092.                 recvmode = 1;    /* got header, looking for
  1093.                          * ZDLE */
  1094.                 /* not gonna get zdle, get B */
  1095.             }
  1096. /*
  1097. ** Got zpad.  If next byte not zpad or zdle, start looking for zpad again
  1098. ** if zpad, continue looking for zdle.
  1099. ** if zdle, look for header type
  1100. */
  1101.             break;
  1102.             case 1:    /* got zpad, looking for zdle */
  1103.             if (m1->m1text[j] == ZPAD)
  1104.                 break;    /* ignore */
  1105.             else if (m1->m1text[j] == ZDLE)
  1106.                 recvmode = 2;
  1107. /*
  1108. ** we must get the 'B' next if this is a ZDLE
  1109. ** we may get the 'B' without a ZDLE. This is OK, we just start
  1110. ** accumulating the header
  1111. */
  1112.  
  1113.             else if (m1->m1text[j] == 'B')
  1114.             {
  1115.                 recvmode = 3;
  1116.                 hdrincnt = 0;
  1117.             }
  1118.             else
  1119.                 recvmode = 0;    /* not one of these - error */
  1120.             break;
  1121.             case 2:    /* got zdle - look for header type. */
  1122.             if (m1->m1text[j] != 'B')
  1123.                 recvmode = 0;    /* must be B */
  1124.             else
  1125.             {
  1126.                 recvmode = 3;    /* start assembling data */
  1127.                 hdrincnt = 0;
  1128.             }
  1129.             break;
  1130. /*
  1131. ** we are now receiving the data packet from the receiver.
  1132. ** It MUST be a hex header, and will be exactly 14 bytes long.
  1133. **  Type(2) plus 4 flags(8) plus 2 CRC bytes(4) = 14
  1134. **    hex encoding, of course
  1135. ** if we get a bad character in, go back to waiting for ZPAD
  1136. */
  1137.             case 3:    /* now assemble the packet */
  1138.             k = m1->m1text[j];
  1139.             if (((k >= '0') && (k <= '9')) || ((k >= 'a') && (k <= 'f')))
  1140.             {
  1141.                 hdrbuf[hdrincnt++] = m1->m1text[j];
  1142.                 if (hdrincnt >= 14)
  1143.                 {
  1144.                 for (j = k = 0; j < 7; j++)
  1145.                 {
  1146.                     n = hdrbuf[k++];
  1147.                     if (n <= '9')
  1148.                     n -= '0';
  1149.                     else
  1150.                     n = (n - 'a') + 10;
  1151.                     m = hdrbuf[k++];
  1152.                     if (m <= '9')
  1153.                     m -= '0';
  1154.                     else
  1155.                     m = (m - 'a') + 10;
  1156.                     hdrbuf[j] = n * 16 + m;
  1157.                 }
  1158.                 recvmode = 0;
  1159.                 return 1;    /* show we got a header */
  1160.                 }
  1161.             }
  1162.             else
  1163.                 recvmode = 0;
  1164.             break;
  1165.         }        /* end switch */
  1166.         }            /* end for */
  1167.     }                /* end switch */
  1168. /*
  1169. ** If we get here, we want to return 0, showing we didn;t get anything
  1170. */
  1171.     return 0;
  1172. }
  1173.  
  1174. check_ring_buf()
  1175. {
  1176.     int n;
  1177.  
  1178.     n = f_status(who);
  1179.     if ((n & 0x100) == 0)    /* anything in input buffer ? */
  1180.     return 0;
  1181.     n = f_recv(who, m1->m1text, 1024);
  1182.     m1->m1text[n] = '\0';
  1183.     m1->m1typ = 2;
  1184.     m1->m1num = n;
  1185.     return 2;
  1186. }
  1187.